home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / move.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-08  |  12.4 KB  |  544 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22.  
  23. #include <gtk/gtk.h>
  24.  
  25. #include "apptypes.h"
  26. #include "appenv.h"
  27. #include "cursorutil.h"
  28. #include "draw_core.h"
  29. #include "edit_selection.h"
  30. #include "floating_sel.h"
  31. #include "gimage_mask.h"
  32. #include "gdisplay.h"
  33. #include "gdisplay_ops.h"
  34. #include "move.h"
  35. #include "undo.h"
  36.  
  37. #include "config.h"
  38. #include "libgimp/gimpintl.h"
  39.  
  40. /*  the move structures  */
  41.  
  42. typedef struct _MoveTool MoveTool;
  43. struct _MoveTool
  44. {
  45.   Layer    *layer;
  46.   Guide    *guide;
  47.   GDisplay *disp;
  48. };
  49.  
  50.  
  51. /*  the move tool options  */
  52. static ToolOptions *move_options = NULL;
  53.  
  54. /*  local variables  */
  55. static GdkGC *move_gc = NULL;
  56.  
  57.  
  58. /*  move tool action functions  */
  59. static void   move_tool_button_press   (Tool *, GdkEventButton *, gpointer);
  60. static void   move_tool_button_release (Tool *, GdkEventButton *, gpointer);
  61. static void   move_tool_motion         (Tool *, GdkEventMotion *, gpointer);
  62. static void   move_tool_cursor_update  (Tool *, GdkEventMotion *, gpointer);
  63. static void   move_tool_control           (Tool *, ToolAction,       gpointer);
  64.  
  65. static void   move_create_gc           (GDisplay *gdisp);
  66.  
  67.  
  68. /*  move action functions  */
  69.  
  70. static void
  71. move_tool_button_press (Tool           *tool,
  72.             GdkEventButton *bevent,
  73.             gpointer        gdisp_ptr)
  74. {
  75.   GDisplay *gdisp;
  76.   MoveTool *move;
  77.   Layer    *layer;
  78.   Guide    *guide;
  79.   gint      x, y;
  80.  
  81.   gdisp = (GDisplay *) gdisp_ptr;
  82.   move = (MoveTool *) tool->private;
  83.  
  84.   tool->gdisp_ptr = gdisp_ptr;
  85.   move->layer = NULL;
  86.   move->guide = NULL;
  87.   move->disp  = NULL;
  88.  
  89.   gdisplay_untransform_coords (gdisp, 
  90.                                bevent->x, bevent->y, &x, &y, FALSE, FALSE);
  91.  
  92.   if (bevent->state & GDK_MOD1_MASK &&
  93.       !gimage_mask_is_empty (gdisp->gimage))
  94.     {
  95.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TRANSLATE);
  96.       tool->state = ACTIVE;
  97.     }
  98.   else if (bevent->state & GDK_SHIFT_MASK)
  99.     {
  100.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_LAYER_TRANSLATE);
  101.       tool->state = ACTIVE;
  102.     }
  103.   else
  104.     {
  105.       if (gdisp->draw_guides &&
  106.       (guide = gdisplay_find_guide (gdisp, bevent->x, bevent->y)))
  107.     {
  108.       undo_push_guide (gdisp->gimage, guide);
  109.  
  110.       gdisplays_expose_guide (gdisp->gimage, guide);
  111.       gimage_remove_guide (gdisp->gimage, guide);
  112.       gdisplay_flush (gdisp);
  113.       gimage_add_guide (gdisp->gimage, guide);
  114.  
  115.       move->guide = guide;
  116.       move->disp  = gdisp;
  117.  
  118.       tool->scroll_lock = TRUE;
  119.       tool->state       = ACTIVE;
  120.  
  121.           selection_pause (gdisp->select);
  122.  
  123.       move_tool_motion (tool, NULL, gdisp);
  124.     }
  125.       else if ((layer = gimage_pick_correlate_layer (gdisp->gimage, x, y)))
  126.     {
  127.       /*  If there is a floating selection, and this aint it,
  128.        *  use the move tool
  129.        */
  130.       if (gimage_floating_sel (gdisp->gimage) &&
  131.           !layer_is_floating_sel (layer))
  132.         {
  133.           move->layer = gimage_floating_sel (gdisp->gimage);
  134.         }
  135.       /*  Otherwise, init the edit selection  */
  136.       else
  137.         {
  138.           gimage_set_active_layer (gdisp->gimage, layer);
  139.           init_edit_selection (tool, gdisp_ptr, bevent, EDIT_LAYER_TRANSLATE);
  140.         }
  141.       tool->state = ACTIVE;
  142.     }
  143.     }
  144.  
  145.   /* if we've got an active tool grab the pointer */
  146.   if (tool->state == ACTIVE)      
  147.     {
  148.       gdk_pointer_grab (gdisp->canvas->window, FALSE,
  149.             GDK_POINTER_MOTION_HINT_MASK |
  150.             GDK_BUTTON1_MOTION_MASK |
  151.             GDK_BUTTON_RELEASE_MASK,
  152.             NULL, NULL, bevent->time);
  153.     }
  154. }
  155.  
  156. static void
  157. move_draw_guide (GDisplay *gdisp, 
  158.          Guide    *guide)
  159. {
  160.   gint x1, y1;
  161.   gint x2, y2;
  162.   gint w, h;
  163.   gint x, y;
  164.  
  165.   if (!move_gc)
  166.     move_create_gc (gdisp);
  167.  
  168.   if (guide->position == -1)
  169.     return;
  170.   
  171.   gdisplay_transform_coords (gdisp, gdisp->gimage->width, 
  172.                  gdisp->gimage->height, &x2, &y2, FALSE); 
  173.  
  174.   gdk_window_get_size (gdisp->canvas->window, &w, &h);
  175.  
  176.   switch (guide->orientation)
  177.     {
  178.     case ORIENTATION_HORIZONTAL:
  179.       gdisplay_transform_coords (gdisp, 0, guide->position, &x1, &y, FALSE);
  180.       if (x1 < 0) x1 = 0;
  181.       if (x2 > w) x2 = w;
  182.  
  183.       gdk_draw_line (gdisp->canvas->window, move_gc, x1, y, x2, y); 
  184.       break;
  185.  
  186.     case ORIENTATION_VERTICAL:
  187.       gdisplay_transform_coords (gdisp, guide->position, 0, &x, &y1, FALSE);
  188.       if (y1 < 0) y1 = 0;
  189.       if (y2 > h) y2 = h;
  190.  
  191.       gdk_draw_line (gdisp->canvas->window, move_gc, x, y1, x, y2);
  192.       break;
  193.  
  194.     default:
  195.       g_warning ("mdg / BAD FALLTHROUGH");
  196.     }
  197. }
  198.  
  199. static void
  200. move_tool_button_release (Tool           *tool,
  201.               GdkEventButton *bevent,
  202.               gpointer        gdisp_ptr)
  203. {
  204.   MoveTool *move;
  205.   GDisplay *gdisp;
  206.   gboolean  delete_guide;
  207.   gint      x1, y1;
  208.   gint      x2, y2;
  209.  
  210.   gdisp = (GDisplay *) gdisp_ptr;
  211.   move = (MoveTool *) tool->private;
  212.  
  213.   gdk_flush ();
  214.  
  215.   tool->state = INACTIVE;
  216.   gdk_pointer_ungrab (bevent->time);
  217.  
  218.   if (move->guide)
  219.     {
  220.       tool->scroll_lock = FALSE;
  221.  
  222.       delete_guide = FALSE;
  223.       gdisplay_untransform_coords (gdisp, 0, 0, &x1, &y1, FALSE, FALSE);
  224.       gdisplay_untransform_coords (gdisp, 
  225.                                    gdisp->disp_width, gdisp->disp_height,
  226.                    &x2, &y2, FALSE, FALSE);
  227.  
  228.       if (x1 < 0) x1 = 0;
  229.       if (y1 < 0) y1 = 0;
  230.       if (x2 > gdisp->gimage->width)  x2 = gdisp->gimage->width;
  231.       if (y2 > gdisp->gimage->height) y2 = gdisp->gimage->height;
  232.  
  233.       switch (move->guide->orientation)
  234.     {
  235.     case ORIENTATION_HORIZONTAL:
  236.       if ((move->guide->position < y1) || (move->guide->position > y2))
  237.         delete_guide = TRUE;
  238.       break;
  239.     case ORIENTATION_VERTICAL:
  240.       if ((move->guide->position < x1) || (move->guide->position > x2))
  241.         delete_guide = TRUE;
  242.       break;
  243.     }
  244.  
  245.       gdisplays_expose_guide (gdisp->gimage, move->guide);
  246.  
  247.       if (delete_guide)
  248.     {
  249.       move_draw_guide (gdisp, move->guide);
  250.       gimp_image_delete_guide (gdisp->gimage, move->guide);
  251.       move->guide = NULL;
  252.       move->disp = NULL;
  253.     }
  254.       else
  255.     {
  256.       move_tool_motion (tool, NULL, gdisp_ptr);
  257.     }
  258.  
  259.       selection_resume (gdisp->select);
  260.       gdisplays_flush ();
  261.  
  262.       if (move->guide)
  263.     gdisplay_draw_guide (gdisp, move->guide, TRUE);
  264.     }
  265.   else
  266.     {
  267.       /*  Take care of the case where the user "cancels" the action  */
  268.       if (! (bevent->state & GDK_BUTTON3_MASK))
  269.     {
  270.       if (move->layer)
  271.         {
  272.           floating_sel_anchor (move->layer);
  273.           gdisplays_flush ();
  274.         }
  275.     }
  276.     }
  277. }
  278.  
  279. static void
  280. move_tool_motion (Tool           *tool,
  281.           GdkEventMotion *mevent,
  282.           gpointer        gdisp_ptr)
  283.  
  284. {
  285.   MoveTool *move;
  286.   GDisplay *gdisp;
  287.   gint      x, y;
  288.  
  289.   move = (MoveTool *) tool->private;
  290.   gdisp = (GDisplay *) gdisp_ptr;
  291.  
  292.   if (move->guide)
  293.     {
  294.       move_draw_guide (gdisp, move->guide);
  295.  
  296.       if (mevent && mevent->window != gdisp->canvas->window)
  297.     {
  298.       move->guide->position = -1;
  299.       return;
  300.     }
  301.       
  302.       if (mevent)
  303.     {
  304.       gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, 
  305.                        &x, &y, TRUE, FALSE);
  306.  
  307.       if (move->guide->orientation == ORIENTATION_HORIZONTAL)
  308.         move->guide->position = y;
  309.       else
  310.         move->guide->position = x;
  311.       
  312.       move_draw_guide (gdisp, move->guide);
  313.     }
  314.     }
  315. }
  316.  
  317. static void
  318. move_tool_cursor_update (Tool           *tool,
  319.              GdkEventMotion *mevent,
  320.              gpointer        gdisp_ptr)
  321. {
  322.   MoveTool *move;
  323.   GDisplay *gdisp;
  324.   Guide    *guide;
  325.   Layer    *layer;
  326.   gint      x, y;
  327.  
  328.   move = (MoveTool *) tool->private;
  329.   gdisp = (GDisplay *) gdisp_ptr;
  330.  
  331.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y,
  332.                    FALSE, FALSE);
  333.  
  334.   if (mevent->state & GDK_MOD1_MASK &&
  335.       !gimage_mask_is_empty (gdisp->gimage))
  336.     {
  337.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  338.                     RECT_SELECT,
  339.                     CURSOR_MODIFIER_MOVE,
  340.                     FALSE);
  341.     }
  342.   else if (mevent->state & GDK_SHIFT_MASK)
  343.     {
  344.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  345.                     MOVE,
  346.                     CURSOR_MODIFIER_NONE,
  347.                     FALSE);
  348.     }
  349.   else
  350.     {
  351.       if (gdisp->draw_guides &&
  352.       (guide = gdisplay_find_guide (gdisp, mevent->x, mevent->y)))
  353.     {
  354.       tool->gdisp_ptr = gdisp_ptr;
  355.       gdisplay_install_tool_cursor (gdisp, GDK_HAND2,
  356.                     TOOL_TYPE_NONE,
  357.                     CURSOR_MODIFIER_HAND,
  358.                     FALSE);
  359.  
  360.       if (tool->state != ACTIVE)
  361.         {
  362.           if (move->guide)
  363.         {
  364.           gdisp = gdisplays_check_valid (move->disp, move->disp->gimage);
  365.           if (gdisp)
  366.             gdisplay_draw_guide (gdisp, move->guide, FALSE);
  367.         }
  368.  
  369.           gdisp = gdisp_ptr;
  370.           gdisplay_draw_guide (gdisp, guide, TRUE);
  371.           move->guide = guide;
  372.           move->disp = gdisp;
  373.         }
  374.     }
  375.       else if ((layer = gimage_pick_correlate_layer (gdisp->gimage, x, y)))
  376.     {
  377.       /*  if there is a floating selection, and this aint it...  */
  378.       if (gimage_floating_sel (gdisp->gimage) &&
  379.           !layer_is_floating_sel (layer))
  380.         gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  381.                       RECT_SELECT,
  382.                       CURSOR_MODIFIER_ANCHOR,
  383.                       FALSE);
  384.       else if (layer == gdisp->gimage->active_layer)
  385.         gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  386.                       MOVE,
  387.                       CURSOR_MODIFIER_NONE,
  388.                       FALSE);
  389.       else
  390.         gdisplay_install_tool_cursor (gdisp, GDK_HAND2,
  391.                       TOOL_TYPE_NONE,
  392.                       CURSOR_MODIFIER_HAND,
  393.                       FALSE);
  394.     }
  395.       else
  396.     {
  397.       gdisplay_install_tool_cursor (gdisp, GIMP_BAD_CURSOR,
  398.                     MOVE,
  399.                     CURSOR_MODIFIER_NONE,
  400.                     FALSE);
  401.     }
  402.     }
  403. }
  404.  
  405.  
  406. static void
  407. move_tool_control (Tool       *tool,
  408.            ToolAction  action,
  409.            gpointer    gdisp_ptr)
  410. {
  411.   MoveTool *move;
  412.  
  413.   move = tool->private;
  414.  
  415.   switch (action)
  416.     {
  417.     case PAUSE:
  418.       break;
  419.  
  420.     case RESUME:
  421.       if (move->guide)
  422.     gdisplay_draw_guide (gdisp_ptr, move->guide, TRUE);
  423.       break;
  424.  
  425.     case HALT:
  426.       break;
  427.  
  428.     default:
  429.       break;
  430.     }
  431. }
  432.  
  433. static void
  434. move_create_gc (GDisplay *gdisp)
  435. {
  436.   if (!move_gc)
  437.     {
  438.       GdkGCValues values;
  439.  
  440.       values.foreground.pixel = gdisplay_white_pixel (gdisp);
  441.       values.function = GDK_INVERT;
  442.       move_gc = gdk_gc_new_with_values (gdisp->canvas->window, &values,
  443.                     GDK_GC_FUNCTION);
  444.     }
  445. }
  446.  
  447. void
  448. move_tool_start_hguide (Tool     *tool,
  449.             GDisplay *gdisp)
  450. {
  451.   MoveTool *private;
  452.  
  453.   selection_pause (gdisp->select);
  454.  
  455.   tool->gdisp_ptr = gdisp;
  456.   tool->scroll_lock = TRUE;
  457.  
  458.   private = tool->private;
  459.  
  460.   if (private->guide && private->disp && private->disp->gimage)
  461.     gdisplay_draw_guide (private->disp, private->guide, FALSE);
  462.  
  463.   private->guide = gimage_add_hguide (gdisp->gimage);
  464.   private->disp  = gdisp;
  465.  
  466.   tool->state = ACTIVE;
  467.  
  468.   undo_push_guide (gdisp->gimage, private->guide);
  469. }
  470.  
  471. void
  472. move_tool_start_vguide (Tool     *tool,
  473.             GDisplay *gdisp)
  474. {
  475.   MoveTool *private;
  476.  
  477.   selection_pause (gdisp->select);
  478.  
  479.   tool->gdisp_ptr = gdisp;
  480.   tool->scroll_lock = TRUE;
  481.  
  482.   private = tool->private;
  483.  
  484.   if (private->guide && private->disp && private->disp->gimage)
  485.     gdisplay_draw_guide (private->disp, private->guide, FALSE);
  486.  
  487.   private->guide = gimage_add_vguide (gdisp->gimage);
  488.   private->disp  = gdisp;
  489.  
  490.   tool->state = ACTIVE;
  491.  
  492.   undo_push_guide (gdisp->gimage, private->guide);
  493. }
  494.  
  495. Tool *
  496. tools_new_move_tool (void)
  497. {
  498.   Tool     *tool;
  499.   MoveTool *private;
  500.  
  501.   /*  The tool options  */
  502.   if (! move_options)
  503.     {
  504.       move_options = tool_options_new (_("Move Tool"));
  505.       tools_register (MOVE, (ToolOptions *) move_options);
  506.     }
  507.  
  508.   tool = tools_new_tool (MOVE);
  509.   private = g_new0 (MoveTool, 1);
  510.  
  511.   private->layer = NULL;
  512.   private->guide = NULL;
  513.   private->disp  = NULL;
  514.  
  515.   tool->auto_snap_to = FALSE;  /*  Don't snap to guides  */
  516.  
  517.   tool->private = (void *) private;
  518.  
  519.   tool->button_press_func   = move_tool_button_press;
  520.   tool->button_release_func = move_tool_button_release;
  521.   tool->motion_func         = move_tool_motion;
  522.   tool->arrow_keys_func     = edit_sel_arrow_keys_func;
  523.   tool->cursor_update_func  = move_tool_cursor_update;
  524.   tool->control_func        = move_tool_control;
  525.  
  526.   return tool;
  527. }
  528.  
  529. void
  530. tools_free_move_tool (Tool *tool)
  531. {
  532.   MoveTool *move;
  533.  
  534.   move = (MoveTool *) tool->private;
  535.  
  536.   if (tool->gdisp_ptr)
  537.     {
  538.       if (move->guide)
  539.     gdisplay_draw_guide (tool->gdisp_ptr, move->guide, FALSE);
  540.     }
  541.  
  542.   g_free (move);
  543. }
  544.